package org.example.myportfolio.common.exception;

import lombok.extern.slf4j.Slf4j;
import org.example.myportfolio.config.response.JsonResult;
import org.example.myportfolio.config.response.StatusCode;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolationException;
import java.io.IOException;

/**
 * 全局异常处理器
 * 1、在控制层抛出异常后
 * 2、创建全局异常处理器的类
 * 控制器异常处理顺序：
 *      1. 在控制器中抛出异常后，定位全局异常处理器
 *      2. 调用对应的异常处理方法进行处理
 *      3. 调用该异常父类异常的处理方法进行处理
 *      4.
 */

/**
 * @ControllerAdvice：
 *      1、将此类标识为全局异常处理器，处理由控制器抛出的异常
 *      2、如果控制器抛出异常后，框架会先检查是否定义了全局异常处理器
 *       2.1 未定义：框架会使用默认的全局异常处理器处理异常[不友好]
 *       2.2 定义了：则到全局异常处理器中找到对应的异常处理方法处理异常
 *
 * @ExceptionHandler：标识该方法处理异常的方法
 * @RestControllerAdvice： 组合注解，相当于@ControllerAdvice + @ResponseBody
 *
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 第一个处理异常的方法【示例】，处理IllegalArgumentException异常
     * 只要返回给客户端，都返回JsonResult
     *
     * ExceptionHandler 是方法注解，标识异常处理方法
     * @param ex
     * @return
     */
    @ExceptionHandler
    public JsonResult doHandleIllegalArgumentException(IllegalArgumentException ex){
        //获取异常信息
        String message = ex.getMessage();
        //在终端打印错误日志
        log.error("IllegalArgumentException："+message);
        //{"state":2002,"message":"操作失败"，"data":"微博编号不能小于0"}
        return JsonResult.fail(message);
    }

    /**
     * 第二个异常处理方法：Validation校验DTO类型的数据合法性；
     */
    @ExceptionHandler
    public JsonResult doHandleMethodArgumentNotValidException
    (MethodArgumentNotValidException ex) {
        /**
         * getFieldError()：获取校验失败的属性
         * getDefaultMessage()：获取校验失败的属性的默认信息
         */
        String message = ex.getFieldError().getDefaultMessage();
        log.error("MethodArgumentNotValidException:"+message);
        return new JsonResult(StatusCode.VALIDATED_ERROR,message);
    }

    /**
     * 第三个异常处理方法：Validation校验参数合法性的异常处理方法
     */
    @ExceptionHandler
    public JsonResult doHandleConstraintViolationException(ConstraintViolationException ex){
        //获取异常信息
        String message = ex.getMessage().split(":")[1].trim();
        log.error("ConstraintViolationException:"+message);
        return new JsonResult(StatusCode.VALIDATED_ERROR,message);
    }

    /**
     * 空指针异常
     * @param ex
     */
   /* @ExceptionHandler
    public JsonResult doHandleNullPointerException(NullPointerException ex){
        String message = ex.getMessage();
        log.error("NullPointerException:"+message);
        return new JsonResult(StatusCode.NULL_POINTER_ERROR,message);
    }*/

    /**
     * IO异常
     */
    @ExceptionHandler
    public JsonResult doHandleIOException(IOException ex){
        String message = ex.getMessage();
        log.error("IOException:"+message);
        return new JsonResult(StatusCode.IO_ERROR,message);
    }


    /**
     * 父类异常,RuntimeException异常
     * @param ex
     * @return
     */
   /* @ExceptionHandler
    public JsonResult doHandleRuntimeException (RuntimeException ex){
        String message = ex.getMessage();
        log.error("RuntimeException:"+message);
        return JsonResult.fail(message);

    }*/

   /**
     * 第五个异常处理方法，能够处理所有异常，一般最后添加此方法
     * @param ex
     * @return
     */
   /* @ExceptionHandler
    public JsonResult doThrowable(Throwable ex){
        String message = ex.getMessage();
        log.error("Throwable:"+message);
        return new JsonResult(StatusCode.THROWABLE_ERROR,message);
    }*/






}
